package cn.spike.rockcc.service.impl;

import cn.spike.rockcc.domain.PayFlow;
import cn.spike.rockcc.domain.PayOrder;
import cn.spike.rockcc.dto.AlipayNotifyDto;
import cn.spike.rockcc.dto.PayMqDto;
import cn.spike.rockcc.dto.PayParamDto;
import cn.spike.rockcc.errorenum.GlobalExceptionCode;
import cn.spike.rockcc.service.IPayFlowService;
import cn.spike.rockcc.service.IPayOrderService;
import cn.spike.rockcc.service.IPayService;
import cn.spike.rockcc.service.IThirdPartyPaymentService;
import cn.spike.rockcc.util.AssertUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.easysdk.factory.Factory;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Map;

/**
 * @author:spike
 * @create:2023-03-22 18:12
 */
@Service
public class PayServiceImpl implements IPayService {

    @Autowired
    private IPayOrderService payOrderService;

    @Autowired
    private IThirdPartyPaymentService thirdPartyPaymentService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private IPayFlowService payFlowService;

    @Override
    public String apply(PayParamDto payParamDto) {
        //通过订单号查询订单
        PayOrder payOrder = payOrderService.selectByOrderNo(payParamDto.getOrderNo());
        //如果没有查询到说明还没有生成支付订单
        AssertUtil.isNotNull(payOrder, GlobalExceptionCode.PAY_ORDER_EXCEPTION);
        //如果支付订单状态不是待处理 - 也不需要继续执行
        AssertUtil.isEquals(payOrder.getPayStatus(),PayOrder.PAY_WAIT,GlobalExceptionCode.PAY_STATUS_EXCEPTION);

        String urlForm = thirdPartyPaymentService.thirdPartApply(payParamDto.getPayType(),payOrder);

        return urlForm;
    }

    @Override
    public String aliPayNotify(AlipayNotifyDto alipayNotifyDto) {
        //将alipayNotifyDto转换为map - 方便验签
        Map map = JSON.parseObject(JSON.toJSONString(alipayNotifyDto), Map.class);
        //验签
        try {
            Boolean boo = Factory.Payment.Common().verifyNotify(map);
            if(!boo)return "fail";
        } catch (Exception e) {
            e.printStackTrace();
        }
        PayFlow payFlow = new PayFlow();
        try {
            payFlow.setNotifyTime( new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(alipayNotifyDto.getNotify_time()));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        payFlow.setSubject(alipayNotifyDto.getSubject());
        payFlow.setTradeNo(alipayNotifyDto.getTrade_no());
        payFlow.setOutTradeNo(alipayNotifyDto.getOut_trade_no());
        payFlow.setTotalAmount(new BigDecimal(alipayNotifyDto.getTotal_amount()));
        payFlow.setTradeStatus(alipayNotifyDto.getTrade_status());
        payFlow.setCode(alipayNotifyDto.getCode());
        payFlow.setMsg(alipayNotifyDto.getMsg());
        payFlow.setPassbackParams(alipayNotifyDto.getPassback_params());
        payFlow.setPaySuccess(alipayNotifyDto.isTradeSuccess());
        String resultDesc = alipayNotifyDto.isTradeSuccess() ? PayFlow.RESULT_SUCCESS:PayFlow.RESULT_FAIL;
        payFlow.setResultDesc(resultDesc);

        //(String txProducerGroup, String destination, Message<?> message, Object arg)
        PayMqDto payMqDto = new PayMqDto();
        PayOrder payOrder = reSetPayOrder(alipayNotifyDto);

        payMqDto.setPayFlow(payFlow);
        payMqDto.setPayOrder(payOrder);

        boolean sendBoo = true;
        while (sendBoo){
            Message<?> message = MessageBuilder.withPayload(JSON.toJSONString(payOrder)).build();
            TransactionSendResult transactionSendResult = rocketMQTemplate.sendMessageInTransaction(
                    "tx-aliPay",
                    "pay-topic:payFlow-tags",
                    message,
                    payMqDto
            );
            sendBoo = !(transactionSendResult.getSendStatus() == SendStatus.SEND_OK);
        }
            return "success";
    }

    @Override
    public void drawback(String orderNo) {
        Wrapper<PayFlow> wrapper = new EntityWrapper<>();
        wrapper.eq("out_trade_no",orderNo);
        PayOrder payOrder = payOrderService.selectByOrderNo(orderNo);
        PayFlow payFlow = payFlowService.selectOne(wrapper);
        AssertUtil.isNotNull(payOrder,GlobalExceptionCode.PAY_FLOW_EXCEPTION);
        AssertUtil.isNotNull(payFlow,GlobalExceptionCode.PAY_FLOW_EXCEPTION);
        thirdPartyPaymentService.thirdPartRefund(payOrder.getPayType(),payFlow);

    }

    private PayOrder reSetPayOrder(AlipayNotifyDto alipayNotifyDto){
        PayOrder payOrder = payOrderService.selectByOrderNo(alipayNotifyDto.getOut_trade_no());
        String trade_status = alipayNotifyDto.getTrade_status();
        if(trade_status.equals(AlipayNotifyDto.TRADE_SUCCESS)){
            payOrder.setPayStatus(PayOrder.PAY_SUCCESS);
            payOrder.setExtParams(AlipayNotifyDto.TRADE_SUCCESS);
        }
        if(trade_status.equals(AlipayNotifyDto.TRADE_CLOSED)){
            payOrder.setPayStatus(PayOrder.PAY_CANCEL);
            payOrder.setExtParams(AlipayNotifyDto.TRADE_CLOSED);
        }
        if(trade_status.equals(AlipayNotifyDto.TRADE_FINISHED)){
            payOrder.setPayStatus(PayOrder.PAY_SUCCESS);
            payOrder.setExtParams(AlipayNotifyDto.TRADE_FINISHED);
        }
        if(trade_status.equals(AlipayNotifyDto.WAIT_BUYER_PAY)){
            payOrder.setPayStatus(PayOrder.PAY_WAIT);
            payOrder.setExtParams(AlipayNotifyDto.WAIT_BUYER_PAY);
        }
        return payOrder;
    }
}
